set nocompatible
set number
set cursorline
set cursorcolumn
set tabstop=4
set shiftwidth=4
set expandtab
set smarttab
set autoindent
set smartindent
set wrap
set linebreak
set showmatch
set matchtime=2

set ignorecase
set smartcase
set incsearch
set hlsearch

set showmode
set showcmd
set wildmenu
set wildmode=longest:full,full
set laststatus=2
set ruler
set title
set scrolloff=5
set sidescrolloff=5
set display+=lastline

set encoding=utf-8
set fileencoding=utf-8
set fileencodings=utf-8
set backspace=indent,eol,start
set hidden
set autoread
set autowrite
set confirm

set lazyredraw
set ttyfast
set timeoutlen=500
set ttimeoutlen=10

syntax enable
syntax on

set background=dark
colorscheme slate

let mapleader = ","

nnoremap j gj
nnoremap k gk
nnoremap <C-h> <C-w>h
nnoremap <C-j> <C-w>j
nnoremap <C-k> <C-w>k
nnoremap <C-l> <C-w>l

nnoremap <silent> <leader>/ :nohlsearch<CR>

nnoremap <leader>bn :bn<CR>
nnoremap <leader>bp :bp<CR>
nnoremap <leader>bd :bd<CR>

nnoremap <leader>w :w<CR>
nnoremap <leader>q :q<CR>
nnoremap <leader>x :x<CR>

nnoremap <leader>tn :tabnew<CR>
nnoremap <leader>tc :tabclose<CR>
nnoremap <leader>tl :tabnext<CR>
nnoremap <leader>th :tabprev<CR>

let g:powershell_bufnr = -1
let g:powershell_window = -1

function! OpenPowershell()
    if g:powershell_window != -1 && win_gotoid(g:powershell_window)
        echo "PowerShell terminal is already open."
        startinsert
        return
    else
        vsplit
        terminal powershell
        let g:powershell_bufnr = bufnr('%')
        let g:powershell_window = win_getid()
        startinsert
        autocmd BufWipeout <buffer> let g:powershell_bufnr = -1 | let g:powershell_window = -1
    endif
endfunction

function! ClosePowershell()
    if g:powershell_bufnr != -1 && bufexists(g:powershell_bufnr)
        let current_win = win_getid()
        if g:powershell_window != -1 && win_gotoid(g:powershell_window)
            call feedkeys("\<C-\\>\<C-n>", 'n')
            call feedkeys("exit\<CR>", 'n')
            call timer_start(150, {-> execute('if win_gotoid(' . g:powershell_window . ') | close! | endif | call win_gotoid(' . current_win . ') | let g:powershell_bufnr = -1 | let g:powershell_window = -1')})
        else
            execute 'bdelete! ' . g:powershell_bufnr
            let g:powershell_bufnr = -1
            let g:powershell_window = -1
        endif
    endif
endfunction

nnoremap <silent> <C-b> :call OpenPowershell()<CR>
nnoremap <silent> <C-e> :call ClosePowershell()<CR>

tnoremap <Esc> <C-\><C-n>

augroup vimrc
    autocmd!
    autocmd BufWritePre * %s/\s\+$//e
    autocmd FileType python setlocal foldmethod=indent
    autocmd FileType javascript,html,css setlocal tabstop=2 shiftwidth=2
    autocmd FileType markdown setlocal wrap linebreak nolist
augroup END

if has('terminal')
    set termwinsize=10x0
endif

let g:netrw_banner = 0
let g:netrw_liststyle = 3
let g:netrw_browse_split = 4
let g:netrw_altv = 1
let g:netrw_winsize = 25

set statusline=%<%f\ %h%m%r%=[%{&ff}]\ %-14.(%l,%c%V%)\ %P

set clipboard=unnamedplus
set mouse=a
set undofile
set undodir=~/.local/share/nvim/undo

if !isdirectory(expand('~/.local/share/nvim/undo'))
    silent! call mkdir(expand('~/.local/share/nvim/undo'), 'p')
endif

inoremap ( ()<Left>
inoremap [ []<Left>
inoremap { {}<Left>
inoremap {<CR> {<CR>}<Esc>O
inoremap {;<CR> {<CR>};<Esc>O

inoremap ' ''<Left>
inoremap " ""<Left>
inoremap ` ``<Left>

inoremap <expr> )  strpart(getline('.'), col('.')-1, 1) == ")" ? "\<Right>" : ")"
inoremap <expr> ]  strpart(getline('.'), col('.')-1, 1) == "]" ? "\<Right>" : "]"
inoremap <expr> }  strpart(getline('.'), col('.')-1, 1) == "}" ? "\<Right>" : "}"
inoremap <expr> '  strpart(getline('.'), col('.')-1, 1) == "'" ? "\<Right>" : "'"
inoremap <expr> "  strpart(getline('.'), col('.')-1, 1) == "\"" ? "\<Right>" : "\""
inoremap <expr> `  strpart(getline('.'), col('.')-1, 1) == "`" ? "\<Right>" : "`"

function! DeletePair()
    let l:line = getline('.')
    let l:col = col('.')
    let l:char = l:line[l:col - 1]
    let l:next_char = l:line[l:col]

    if l:char == '(' && l:next_char == ')'
        return "\<Del>"
    elseif l:char == '[' && l:next_char == ']'
        return "\<Del>"
    elseif l:char == '{' && l:next_char == '}'
        return "\<Del>"
    elseif l:char == "'" && l:next_char == "'"
        return "\<Del>"
    elseif l:char == '"' && l:next_char == '"'
        return "\<Del>"
    elseif l:char == '`' && l:next_char == '`'
        return "\<Del>"
    else
        return "\<BS>"
    endif
endfunction

inoremap <expr> <BS> DeletePair()

inoremap <expr> <CR> pumvisible() ? "\<C-y>" :
    \ strpart(getline('.'), col('.')-2, 2) =~ '{$' ? "\<CR>\<Esc>O" : "\<CR>"

inoremap <C-l> <Right>

augroup BracketAutoComplete
    autocmd!
    autocmd FileType html inoremap < <><Left>
    autocmd FileType xml inoremap < <><Left>
    autocmd FileType markdown inoremap ` ``<Left>
augroup END

inoremap ' ''<Left>
inoremap " ""<Left>
autocmd FileType python inoremap """ """<Left><Left>
autocmd FileType python inoremap ''' '''<Left><Left>
autocmd FileType javascript inoremap ` ``<Left>

let g:netrw_browse_split = 4
let g:netrw_winsize = 80
let g:netrw_liststyle = 3
let g:netrw_altv = 1
let g:netrw_preview = 1
let g:netrw_dirhistmax = 0
let g:netrw_left = 1

set fillchars=eob:\ 

function! CompileRunTerminal()
    silent write

    let l:filename = expand('%:p')      
    let l:basename = expand('%:r')      
    let l:filetype = &filetype          

    if l:filetype == 'cpp'
        let l:cmd = 'g++ -std=c++11 "' . l:filename . '" -o "' . l:basename . '.exe" && "' . l:basename . '.exe"'
    elseif l:filetype == 'c'
        let l:cmd = 'gcc "' . l:filename . '" -o "' . l:basename . '.exe" && "' . l:basename . '.exe"'
    elseif l:filetype == 'python'
        let l:cmd = 'python "' . l:filename . '"'
    else
        return
    endif

    execute 'belowright split | terminal ' . l:cmd
    
    startinsert
endfunction

nnoremap <F10> :call CompileRunTerminal()<CR>
inoremap <F10> <Esc>:call CompileRunTerminal()<CR>

nnoremap <C-v> <Esc>"+pa
nnoremap <C-c> <Esc>"+y
nnoremap <C-x> <Esc>"+x
nnoremap <C-a> <Esc>ggVG
